import { CsvManager_blxf } from "../Manager/CsvManager";
import { ConfigModule_blxf } from "../Module/ConfigModule";
import { NumModule_blxf } from "../Module/NumModule";
import { UtilsModule_blxf } from "../Module/UtilsModule";
import GameData_blxf from "./GameData";
import { GridItemData_blxf } from "./GridItemData";




/** 网格列表数据 */
export class GridListData_blxf {

    private constructor () {

    }

    private static _gridListData_blxf: GridListData_blxf = new GridListData_blxf();

    public static get instance () {
        return this._gridListData_blxf;
    }

    /** 数据列表 */
    dataList: GridItemData_blxf[] = [];

    /** 叠加记录 */
    moveRecords: any[] = [];
    moveButtonN: number = 0;
    // 周围按钮数
    aroundButtonN: number = 99999;
    // 可移动按钮数
    moveAlikeN: number = 0;
    /** 移动至障碍周围累加次数 */
    toObstacleAroundN: number = 0;

    /** 已出颜色列表 */
    numList1: number[] = [];
    /** 不一致颜色列表 */
    numList2: number[] = [];

    /** 相同披萨基础间隔Y */
    static alikeBaseY: number = 10;

    static alikeStartY: number = 43 || 0.01 || 10;

    /** 初始化网格数据 */
    initGridList_blxf () {
        this.dataList.length = 0;

        this.numList1.length = 0;
        this.numList2.length = 0;
        
        // let { gridRows, gridColumns } = ConfigModule_blxf;
        // for ( let rowN = 1; rowN <= gridRows; rowN++ ) {
        //     for ( let colN = 1; colN <= gridColumns; colN++ ) {
        //         let _options = { rowN, colN, gridType: 1 };
        //         let _gridItemData = new GridItemData_blxf( _options );
        //         this.dataList.push( _gridItemData );
        //     }
        // }
        let _gridDataList = CsvManager_blxf.instance.getPassData_blxf();
        _gridDataList.forEach( item =>{
            let { rowN, colN, _isGrid, _isUnlock } = item;
            if ( !_isGrid ) return;

            let _options = { rowN, colN, gridType: 1, isUnlock: _isUnlock };
            let _gridItemData = new GridItemData_blxf( _options );
            this.dataList.push( _gridItemData );
        })
        // cc.log('dataList >>', this.dataList);
    }

    /** 解锁网格数据 */
    onUnlockGridItemData_blxf ( rowN: number, colN: number ) {
        let _gridData: GridItemData_blxf = this.findGrid_blxf( rowN, colN );
        _gridData.setUnlock_blxf();

        _gridData.updateGridData_blxf();
    }

    /** 添加网格纽扣数据 */
    addGridButton_blxf ( _gridItemData: GridItemData_blxf, buttonData: any ) {
        _gridItemData.addButtonData_blxf( buttonData );

        _gridItemData.updateGridData_blxf();
    }

    /**
     * 移除网格纽扣数据
     * @param rowN 行
     * @param colN 列
     * @param buttonId 纽扣id 
     */
    removeGridButton_blxf ( rowN: number, colN: number, buttonId: number ) {
        let _gridData: GridItemData_blxf = this.findGrid_blxf( rowN, colN );
         buttonId && _gridData.removeButtonData_blxf( buttonId );
        !buttonId && _gridData.clearAllButtonData_blxf();

        _gridData.updateGridData_blxf();
    }

    //  0 1 2 3 4 5 6 7 8 9
    //0   1   3   5   7   9
    //1 0   2   4   5   8
    //2   1   3   5   7   9
    //3 0   2   4   5   8
    //4   1   3   5   7   9
    
    /**
     * 正六边形(6个方位)
     * @param type 1正上、2正下、3左上、4左下、5右上、6右下
     * @returns 返回偏移量
     */
    onDirectionData_blxf ( type: number ) {
        let _x: number, _y: number;

        // // 正四边形
        // switch ( type ) {
        //     // 正上
        //     case 1 : _x =  0, _y = -1; break;
        //     // 正下
        //     case 2 : _x =  0, _y =  1; break;
        //     // 正左
        //     case 3 : _x = -1, _y =  0; break;
        //     // 正右
        //     case 4 : _x =  1, _y =  0; break;
        // }

        // 正六边形
        switch ( type ) {
            // 1正上: x+0 / y-2
            case 1 : _x =  0, _y = -2; break;
            // 2正下: x+0 / y+2
            case 2 : _x =  0, _y =  2; break;
            // 3左上: x-1 / y-1
            case 3 : _x = -1, _y = -1; break;
            // 4左下: x-1 / y+1
            case 4 : _x = -1, _y =  1; break;
            // 5右上: x+1 / y-1
            case 5 : _x =  1, _y = -1; break;
            // 6右下: x+1 / y+1
            case 6 : _x =  1, _y =  1; break;
        }

        return { x: _x, y: _y };
    }

    /**
     * 获取方向数据列表
     * @returns 返回方向数据列表
     */
    onDirectionDataList_blxf () {
        let _dataList: any[] = [];

        for ( let type = 1; type <= 6; type++ ) {
            let _data: any = this.onDirectionData_blxf( type );
            _data && _dataList.push( _data );
        }

        return _dataList;
    }

    /** 获取可叠加纽扣id列表 */
    getTopButtonIdList_blxf () {
        let _buttonIdList: number[] = [];
        
        this.dataList.forEach( item =>{
            let { rowN, colN } = item.getGridPos_blxf();

            // 检测四周格子有无已解锁空置网格
            let _isHave: boolean = false;
            // for ( let i = -1; i <= 1; i++ ) {
            //     for ( let j = -1; j <= 1; j++ ) {
            //         if ( i != 0 && j != 0 ) continue;
            //         if ( i == 0 && j == 0 ) continue;

            //         let _rowN: number = rowN + i;
            //         let _colN: number = colN + j;

            //         // 网格不存在
            //         let _checkGridData: GridItemData_blxf = this.findGrid_blxf( _rowN, _colN );
            //         if ( !_checkGridData ) continue;

            //         let _isUnlock: boolean = _checkGridData.onCheckIsUnlock_blxf();
            //         if ( !_isUnlock ) continue;

            //         let _buttonId: number = _checkGridData.getTopButtonId_blxf();
            //         if ( _buttonId ) continue;

            //         _isHave = true;
            //     }
            // }

            // 六边形检测
            let _aroundDataList: any[] = this.onDirectionDataList_blxf();
            _aroundDataList.forEach( dataItem =>{
                let { x, y } = dataItem;
                let _rowN: number = rowN + y;
                let _colN: number = colN + x;

                let _checkGridData: GridItemData_blxf = this.findGrid_blxf( _rowN, _colN );
                if ( !_checkGridData ) return;

                let _isUnlock: boolean = _checkGridData.onCheckIsUnlock_blxf();
                if ( !_isUnlock ) return;

                let _buttonId: number = _checkGridData.getTopButtonId_blxf();
                if ( _buttonId ) return;

                _isHave = true;
            })

            if ( !_isHave ) return;

            let _buttonId: number = item.getTopButtonId_blxf();
            if ( !_buttonId ) return;
            let _isCheck = _buttonIdList.includes( _buttonId );
            if ( _isCheck ) return;
            _buttonIdList.push( _buttonId );
        })

        _buttonIdList.sort((a, b) => Math.random() - 0.5);

        return _buttonIdList;
    }

    // 1、纽扣消除逻辑
    // 第一步：检测放置网格和相邻四个网格是否可堆叠
    // 第二步：再测相邻四个网格的相邻网格是否可堆叠
    // 第三步：以此类推
    // 注意事项 1：判断最佳堆叠

    onGridDataList_blxf ( dataList: GridItemData_blxf[] = null ) {
        let _dataList: GridItemData_blxf[] = [];

        if ( !dataList ) dataList = this.dataList;
        dataList.forEach( ( gridItemData ) =>{
            let { rowN, colN } = gridItemData.getGridPos_blxf();
            let { obstacleType, obstacleState } = gridItemData.getObstacleInfo_blxf();
            let _buttonIdList: number[] = gridItemData.getGridButtonIdList_blxf();
            let _buttonIdNumList: number[] = gridItemData.getGridButtonIdNumList_blxf();

            let _gridItemData = new GridItemData_blxf({ rowN, colN, gridType: -1, obstacleType, obstacleState });
            _buttonIdList.forEach( (buttonId: number, index) =>{
                let _buttonIdN: number = _buttonIdNumList[ index ];
                _gridItemData.addButtonData_blxf( { buttonId, num: _buttonIdN } );
            })

            _dataList.push( _gridItemData );
        })

        return _dataList;
    }

    /**
     * 检测叠加
     */
    onCheckMove_blxf ( checkRowN: number, checkColN: number, gridDataList: GridItemData_blxf[] = null, moveRecords: any[] = [], checkN: number = 0 ) {
        // cc.warn(checkN, '<<== checkN & checkRowN & checkColN >>', checkRowN, checkColN);
        if ( !gridDataList ) {
            gridDataList = this.onGridDataList_blxf();
            // 初始化
            this.moveButtonN = -1;
            this.moveAlikeN = 999;
            this.toObstacleAroundN = 0;
            this.aroundButtonN = 999999;
            this.moveRecords.length = 0;
        }

        let { gridButtonId, gridData, checkList } = this.onCheckGridList_blxf( checkRowN, checkColN, gridDataList );
        
        let _checkNum: number = checkList.length;
        // 无可叠加网格
        if ( _checkNum == 0 ) return -1;

        checkN += 1;

        // 都可叠
        // 判断下层纽扣是否可叠
        // 网格次数越多越不能往其叠

        // 叠(检测往哪边叠) -> 消 -> 递归
        // 1:检测叠后纽扣是否可和相邻网格继续叠，2:检测叠后纽扣的类型数
        // 两边都满足的情况下先比较1，再比较2

        // 注：如何记录已叠纽扣, 如何寻找最优解(权重分配：可叠次数、纽扣种类数)

        // 2个2种、3个3种、4个4种、5个5种
        // 记录叠加过程

        // 合并可叠网格
        let _checkList: GridItemData_blxf[] = [ gridData, ...checkList ];
        // cc.log('checkList >11>', gridButtonId, JSON.parse(JSON.stringify(_checkList)));
        _checkList.forEach(( gridDataItem, index ) =>{
            // cc.error(`forEach ===> ${checkN}_${index}`);
            // 复制网格数据、复制移动记录
            let _moveRecords: any[] = [ ...moveRecords ];
            let _gridDataList1: GridItemData_blxf[] = this.onGridDataList_blxf( gridDataList );

            // 复制可移动网格
            let _copyCheckList: GridItemData_blxf[] = [], _gridPosList: any[] = [];
            _checkList.forEach( gridDataItem1 =>{
                let { rowN, colN } = gridDataItem1.getGridPos_blxf();
                let _gridData = this.findGrid_blxf( rowN, colN, _gridDataList1 );
                _copyCheckList.push( _gridData );
                _gridPosList.push(`${rowN}_${colN}`);
                // _gridPosList.push({ rowN, colN });
            })
            
            // 移动纽扣（模拟）
            let _addRecords: any[] = [];
            let _toGrid: any = _gridPosList[ index ], _checkGrid: any = _gridPosList[ 0 ];
            let _maxNum: number = this.onCheckGridButtonNum_blxf( _toGrid, _gridDataList1 );
            _copyCheckList.forEach(( gridDataItem2, index2 ) =>{
                if ( index == index2 ) {
                    let _data: any = { buttonId: gridButtonId };
                    _copyCheckList[ index ].addButtonData_blxf( _data );
                    return;
                }

                let _alikeN: number = gridDataItem2.getTopButtonIdNum_blxf();
                gridDataItem2.removeButtonData_blxf( gridButtonId );

                // 移除网格剩余纽扣类型数
                let _gridButtonIdList: number[] = gridDataItem2.getGridButtonIdList_blxf();
                let _buttonIdNum: number = _gridButtonIdList.length;

                // 记录移动(按正确步骤修正)
                // 叠至中心网格：周边网格叠至中心网格
                // 叠至周边网格：周边网格先叠至中心网格再叠至周边网格
                let _toGrid2: any = index2 == 0 ? _toGrid : _checkGrid;

                // 计算叠至障碍周围次数
                let [ _toRowN, _toColN ] = _toGrid2.split('_');
                let _obstacleNum: number = this.onCheckAroundObstacle_blxf( Number(_toRowN), Number(_toColN) );

                _addRecords.push({ 
                    inGrid: _gridPosList[ index2 ], toGrid: _toGrid2, 
                    buttonId: gridButtonId, buttonIdNum: _buttonIdNum, maxNum: _maxNum, alikeN: _alikeN,
                    obstacleNum: _obstacleNum
                });
                // 检测周围相邻网格最上层纽扣数量，获取最大纽扣数量，越大可能性越小
            })

            // 倒序
            if ( index != 0 ) _addRecords.reverse();
            _moveRecords = _moveRecords.concat( _addRecords );
            // if ( index == 0 ) cc.log('_moveRecords >00>', _moveRecords, _addRecords);
            // cc.log('checkList >22>', _copyCheckList, _gridDataList1);

            // 2：检测可叠网格的相邻网格
            _copyCheckList.forEach( gridDataItem =>{
                // 空网格
                let _isNull: boolean = gridDataItem.onCheckNull_blxf();
                if ( _isNull ) return;

                // 是否是障碍
                let _isObstacle: boolean = gridDataItem.onCheckObstacle_blxf();
                if ( _isObstacle ) return;

                let { rowN, colN } = gridDataItem.getGridPos_blxf();
                // // 复制已叠加后的网格数据列表
                // let _gridDataList2: GridItemData_blxf[] = this.onGridDataList_blxf( _gridDataList1 );
                let _result: any = this.onCheckMove_blxf( rowN, colN, _gridDataList1, [ ..._moveRecords ], checkN );
                
                // 不可与周围网格叠加时
                if ( _result == -1 ) {
                    // todo 检测是否可消
                    

                    // cc.log('_moveRecords >>', checkN, _moveRecords);
                    this.onCheckRecords_blxf( _moveRecords );
                }
            })
        })
    }

    /** 检测周围障碍数 */
    onCheckAroundObstacle_blxf ( rowN: number, colN: number ) {
        let _obstacleNum: number = 0;

        let _rowN: number, _colN: number;
        // 六边形检测
        let _aroundDataList: any[] = this.onDirectionDataList_blxf();
        _aroundDataList.forEach( dataItem =>{
            let { x, y } = dataItem;
            _rowN = rowN + y;
            _colN = colN + x;

            // 网格不存在
            let _checkGridData: GridItemData_blxf = this.findGrid_blxf( _rowN, _colN );
            if ( !_checkGridData ) return;

            // 是否是障碍
            let _isObstacle: boolean = _checkGridData.onCheckObstacle_blxf();
            if ( !_isObstacle ) return;

            _obstacleNum += 1;
        })

        return _obstacleNum;
    }

    /**
     * 获取网格周围最大可移动纽扣数
     * @param rowN 
     * @param colN 
     * @param gridDataList 
     */
    onCheckGridButtonNum_blxf ( posStr: string, gridDataList: any[] ) {
        let _maxButtonNum: number = 0;

        let [ rowN, colN ] = posStr.split('_');
        // for ( let i = -1; i <= 1; i++ ) {
        //     for ( let j = -1; j <= 1; j++ ) {
        //         if ( i == 0 && j == 0 ) continue;
        //         if ( i != 0 && j != 0 ) continue;

        //         let _rowN: number = Number( rowN ) + i;
        //         let _colN: number = Number( colN ) + j;
        //         let _gridItemData: GridItemData_blxf = this.findGrid_blxf( _rowN, _colN, gridDataList );
        //         if ( !_gridItemData ) continue;

        //         let _buttonNum: number = _gridItemData.getTopButtonIdNum_blxf();
        //         if ( _buttonNum > _maxButtonNum ) _maxButtonNum = _buttonNum;
        //     }
        // }

        // 六边形检测
        let _aroundDataList: any[] = this.onDirectionDataList_blxf();
        _aroundDataList.forEach( dataItem =>{
            let { x, y } = dataItem;
            let _rowN: number = Number( rowN ) + y;
            let _colN: number = Number( colN ) + x;
            
            let _gridItemData: GridItemData_blxf = this.findGrid_blxf( _rowN, _colN, gridDataList );
            if ( !_gridItemData ) return;

            let _buttonNum: number = _gridItemData.getTopButtonIdNum_blxf();
            if ( _buttonNum > _maxButtonNum ) _maxButtonNum = _buttonNum;
        })

        return _maxButtonNum;
    }

    /**
     * 检测叠加记录
     * @param moveRecords 叠加记录
     */
    onCheckRecords_blxf ( moveRecords: any[] ) {
        let _recordLen: number = moveRecords.length;
        let _isCheck: boolean = _recordLen >= this.moveRecords.length;
        if ( !_isCheck ) return;

        let _n: number = 0, _aroundN: number = 0, _alikeN: number = 0, _obstacleNum: number = 0;
        moveRecords.forEach( ( recordItem, index ) =>{
            let { inGrid, toGrid, buttonIdNum, maxNum, alikeN, obstacleNum } = recordItem;
            _n += buttonIdNum;
            _alikeN += alikeN;
            _obstacleNum += obstacleNum;
            
            if ( _aroundN == 0 ) _aroundN = maxNum;
        });

        // 叠加少
        if ( moveRecords.length < this.moveRecords.length ) return;
        
        // // 叠一次: 同颜色从小到大，同大小优先向放置目标靠拢
        // if ( moveRecords.length == 1 ) {
        //     cc.log('moveRecords >>', [ ...moveRecords ]);
        // }

        // todo 判定不够准确
        let _isAlikeLen: boolean = moveRecords.length == this.moveRecords.length;

        if ( _isAlikeLen ) {
            // 纽扣移动至障碍周围从大到小
            if ( _obstacleNum < this.toObstacleAroundN ) return;
            // 纽扣移动数从小到大
            if ( _alikeN >= this.moveAlikeN ) return;
            // 纽扣移动至所在网格的周围最大可移动纽扣数
            if ( _aroundN > this.aroundButtonN ) return;
            // 纽扣移开后剩余纽扣类型数
            if ( _n < this.moveButtonN ) return;

            // // 相同叠加方式下，需随机一种
            // let _isAlike: boolean = _n == this.moveButtonN;
            // if ( _isAlike && NumModule_blxf.instance.isChance_blxf('90%') ) return;
        }

        this.toObstacleAroundN = _obstacleNum;
        this.moveButtonN = _n;
        this.moveAlikeN = _alikeN;
        this.aroundButtonN = _aroundN;
        this.moveRecords = [ ...moveRecords ];
        // cc.log('this.moveRecords >>', _n, [ ...this.moveRecords ]);
    }

    /** 获取叠加记录 */
    getMoveRecords_blxf () {
        return this.moveRecords;
    }

    /**
     * 检测网格列表
     * @param rowN 行数
     * @param colN 列数
     */
    onCheckGridList_blxf ( rowN: number, colN: number, gridDataList: GridItemData_blxf[] = null ) {
        let _checkList: GridItemData_blxf[] = [ ];

        let _gridData: GridItemData_blxf = this.findGrid_blxf( rowN, colN, gridDataList );

        // 是否是障碍
        let _isObstacle: boolean = _gridData.onCheckObstacle_blxf();
        if ( _isObstacle ) return { checkList: _checkList };

        let _gridButtonId: number = _gridData.getTopButtonId_blxf();

        let _rowN: number, _colN: number;
        // for ( let i = -1; i <= 1; i++ ) {
        //     if ( !_gridButtonId ) break;
        //     for ( let j = -1; j <= 1; j++ ) {
        //         // 过滤非相邻网格和本身
        //         if ( i != 0 && j != 0 ) continue;
        //         if ( i == 0 && j == 0 ) continue;

        //         _rowN = rowN + i;
        //         _colN = colN + j;

        //         // 网格不存在
        //         let _checkGridData: GridItemData_blxf = this.findGrid_blxf( _rowN, _colN, gridDataList );
        //         if ( !_checkGridData ) continue;

        //         // 纽扣是否相同
        //         let _checkButtonId: number = _checkGridData.getTopButtonId_blxf();
        //         let _isAlike: boolean = _checkButtonId == _gridButtonId;
        //         if ( !_isAlike ) continue;

        //         _checkList.push( _checkGridData );
        //     }
        // }

        // 六边形检测
        let _aroundDataList: any[] = this.onDirectionDataList_blxf();
        _aroundDataList.forEach( dataItem =>{
            if ( !_gridButtonId ) return;

            let { x, y } = dataItem;
            _rowN = rowN + y;
            _colN = colN + x;

            // 网格不存在
            let _checkGridData: GridItemData_blxf = this.findGrid_blxf( _rowN, _colN, gridDataList );
            if ( !_checkGridData ) return;

            // 是否是障碍
            let _isObstacle: boolean = _checkGridData.onCheckObstacle_blxf();
            if ( _isObstacle ) return;

            // 纽扣是否相同
            let _checkButtonId: number = _checkGridData.getTopButtonId_blxf();
            let _isAlike: boolean = _checkButtonId == _gridButtonId;

            _isAlike && _checkList.push( _checkGridData );
        })

        // cc.log('_checkList >>', _checkList);
        return { gridButtonId: _gridButtonId, gridData: _gridData, checkList: _checkList };
    }

    /**
     * 查找网格
     * @param rowN 行
     * @param colN 列
     * @param gridDataList 网格数据列表 
     * @returns 返回网格
     */
    findGrid_blxf ( rowN: number, colN: number, gridDataList: GridItemData_blxf[] = null ) {
        if ( !gridDataList ) gridDataList = this.dataList;

        let _gridData: GridItemData_blxf = gridDataList.find( gridDataItem =>{
            let _isCheck = gridDataItem.onCheckGridPos_blxf( rowN, colN );
            return _isCheck;
        })
        
        return _gridData;
    }

    getGridButtonIds_blxf ( rowN: number, colN: number ) {
        let _buttonIds: number[] = [];

        let _gridData: GridItemData_blxf = this.findGrid_blxf( rowN, colN );
        if ( !_gridData ) return _buttonIds;

        _buttonIds = _gridData.getGridButtonAllIds_blxf();
        return _buttonIds;
    }

    /**
     * 获取可消除的纽扣数据列表
     * @returns 返回纽扣数据列表
     */
    getRemoveButtonData_blxf () {
        let _buttonDataList: any[] = [];

        this.dataList.forEach(( gridDataItem ) =>{
            let _buttonId: number = gridDataItem.onCheckRemoveOk_blxf();
            if ( !_buttonId ) return;

            let { rowN, colN } = gridDataItem.getGridPos_blxf();
            _buttonDataList.push({ rowN, colN, buttonId: _buttonId });

            // 更新六边形周围障碍物状态
            this.updateAroundObstacleState_blxf( rowN, colN );
        })

        return _buttonDataList;
    }

    /** 更新六边形周围障碍物状态 */
    updateAroundObstacleState_blxf ( rowN: number, colN: number ) {
        let _aroundDataList: any[] = this.onDirectionDataList_blxf();
        _aroundDataList.forEach( dataItem =>{
            let { x, y } = dataItem;
            let _rowN: number = rowN + y;
            let _colN: number = colN + x;

            let _gridData: GridItemData_blxf = this.findGrid_blxf( _rowN, _colN );
            if ( !_gridData ) return;

            let _isObstacle: boolean = _gridData.onCheckObstacle_blxf();
            if ( !_isObstacle ) return;

            _isObstacle && _gridData.updateObstacleState_blxf();
        })
    }

    // 统计网格纽扣类型总数
    onGridButtonIdList_blxf () {
        let _buttonIdNum: number = 0, _buttonIdList: number[] = [];

        this.dataList.forEach( gridDataItem =>{
            let _buttonIds: number[] = gridDataItem.getGridButtonIdList_blxf();
            _buttonIds.forEach( buttonId =>{
                let _isCheck: boolean = _buttonIdList.includes( buttonId );
                !_isCheck && _buttonIdList.push( buttonId );
            })
        })
        UtilsModule_blxf.instance.Log_blxf([ '_buttonIdList >>', _buttonIdList ]);

        _buttonIdNum = _buttonIdList.length;
        return _buttonIdList;
    }

    /** 检测网格是否已满 */
    onCheckAllGrid_blxf () {
        let _isAll: boolean = true;

        this.dataList.forEach( gridDataItem =>{
            if ( !_isAll ) return;

            let _isNull: boolean = gridDataItem.onCheckNull_blxf();
            if ( _isNull ) _isAll = false;
        })

        return _isAll;
    }


    /** 获取保存的网格数据 */
    getSaveGridData_blxf () {
        let _gridPosList: any[] = [], _gridButtonDataList: any[] = [];

        let _gridDataList: any[] = GameData_blxf.instance.getGridDataList_blxf();
        _gridDataList.forEach( item =>{
            let { rowN, colN, dataList } = item;
            _gridPosList.push({ rowN, colN });
            _gridButtonDataList.push({ _numList: dataList });
        })

        // 引导数据
        let _isGui: boolean = GameData_blxf.instance.getIsGuidanceJenga_blxf();
        if ( !_isGui ) {
            _gridPosList = [
                { rowN: 5, colN: 2 },
                { rowN: 5, colN: 4 }
            ]

            _gridButtonDataList = [
                { _numList: [ 1, 1, 1, 1, 1 ]},
                { _numList: [ 2, 2, 2, 2, 2 ]}
            ]
        }

        return { _gridPosList, _gridButtonDataList };
    }

    /** 获取保存的派发数据 */
    getSaveSendData_blxf () {
        let _sendButtonDataList: any[] = [];

        let _sendDataList: any[] = GameData_blxf.instance.getSendDataList_blxf();
        _sendDataList.forEach( item =>{
            let { dataList } = item;
            _sendButtonDataList.push({ _numList: dataList });
        })

        // 引导数据
        let _isGui: boolean = GameData_blxf.instance.getIsGuidanceJenga_blxf();
        if ( !_isGui ) {
            _sendButtonDataList = [
                { _numList: [ 1, 1, 1, 1, 1 ] },
                { _numList: [ 2, 2, 2, 2, 2 ] },
                { _numList: [ 3, 3, 3, 3, 3 ] }
            ]
        }

        return _sendButtonDataList;
    }


    /** 检测是否触发空格派发同色纽扣 */
    onCheckNullGridRatio_blxf () {
        let _nullNum: number = 0;
        let _maxNum: number = this.dataList.length;
        let _isHaveUnlock: boolean = false;

        this.dataList.forEach( item =>{
            let _isUnlock: boolean = item.onCheckIsUnlock_blxf();
            if ( !_isUnlock ) return _isHaveUnlock = true;

            let _buttonIds: number[] = item.getGridButtonAllIds_blxf();
            let _isNull: boolean = _buttonIds.length == 0;
            if ( !_isNull ) return;

            _nullNum += 1;
        })

        let _nullRatio: number = _nullNum / _maxNum;
        let _isTrigger: boolean = _isHaveUnlock && _nullRatio <= ConfigModule_blxf.nullGridRatio
        return _isTrigger;
    }

    /** 检测视频周围网格颜色最多的纽扣 */
    onCheckVideoButtonId_blxf () {
        let _buttonId: number;

        let _videoDataList: GridItemData_blxf[] = this.dataList.filter( item =>{
            return !item.isUnlock;
        })
        if ( _videoDataList.length == 0 ) return _buttonId;

        let _buttonIdN: number = 0;
        _videoDataList.forEach( item =>{
            let _list: any[] = [];
            let { rowN, colN } = item.getGridPos_blxf();

            // for ( let i = -1; i <= 1; i++ ) {
            //     for ( let j = -1; j <= 1; j++ ) {
            //         if ( i * j != 0 ) continue;
            //         if ( i == 0 && j == 0 ) continue;

            //         let _rowN: number = rowN + i;
            //         let _colN: number = colN + j;
            //         let _gridData = this.findGrid_blxf( _rowN, _colN );
            //         if ( !_gridData ) continue;

            //         let _num: number = _gridData.getTopButtonIdNum_blxf();
            //         let _buttonId: number = _gridData.getTopButtonId_blxf();
            //         let _index: number = _list.findIndex( item => item.buttonId == _buttonId );
            //         if ( _index == -1 ) {
            //             _list.push({ buttonId: _buttonId, num: _num });
            //         } else {
            //             _list[ _index ].num += _num;
            //         }
            //     }
            // }

            // 六边形检测
            let _aroundDataList: any[] = this.onDirectionDataList_blxf();
            _aroundDataList.forEach( dataItem =>{
                let { x, y } = dataItem;
                let _rowN: number = rowN + y;
                let _colN: number = colN + x;

                let _gridData: GridItemData_blxf = this.findGrid_blxf( _rowN, _colN );
                if ( !_gridData ) return;

                let _num: number = _gridData.getTopButtonIdNum_blxf();
                let _buttonId: number = _gridData.getTopButtonId_blxf();
                let _index: number = _list.findIndex( item => item.buttonId == _buttonId );
                if ( _index == -1 ) {
                    _list.push({ buttonId: _buttonId, num: _num });
                } else {
                    _list[ _index ].num += _num;
                }
            })
            
            _list.sort((a, b) => b.num - a.num);

            let { buttonId, num } = _list[0];
            if ( num <= _buttonIdN ) return;

            _buttonId = buttonId, _buttonIdN = num;
        })

        return _buttonId;
    }

    /**
     * 检测空网格周围堆叠最上层数据
     * @returns 返回最上层数据
     */
    onCheckNullGridAroundData_blxf () {
        let _data: any[] = [];

        let _aroundDataList: any[] = this.onDirectionDataList_blxf();
        let _nullDataList: GridItemData_blxf[] = this.dataList.filter( item =>{
            let _isNull: boolean = item.onCheckNull_blxf();
            return _isNull;
        })

        _nullDataList.forEach( item =>{
            let { rowN, colN } = item.getGridPos_blxf();
            _aroundDataList.forEach( dataItem =>{
                let { x, y } = dataItem;
                let _rowN: number = rowN + y;
                let _colN: number = colN + x;

                let _gridData: GridItemData_blxf = this.findGrid_blxf( _rowN, _colN );
                if ( !_gridData ) return;

                let _topButtonId: number = _gridData.getTopButtonId_blxf();
                if ( !_topButtonId ) return;
                
                let _topButtonNum: number = _gridData.getTopButtonIdNum_blxf();
                let _index: number = _data.findIndex( item =>{
                    return item.buttonId == _topButtonId;
                })
                if ( _index == -1 ) {
                    _data.push({ buttonId: _topButtonId, buttonNum: _topButtonNum });
                } else {
                    let _buttonNum: number = _data[ _index ].buttonNum;
                    if ( _topButtonNum > _buttonNum ) {
                        _data[ _index ].buttonNum = _topButtonNum;
                    }
                }
            })
        })

        return _data;
    }
    
    /**
     * 检测空格周围网格堆叠最上层颜色列表
     */
    onCheckNullGridAround_blxf () {
        let _buttonIdList: number[] = [];

        let _topButtonData: any[] = this.onCheckNullGridAroundData_blxf();
        _topButtonData.forEach( item =>{
            let { buttonId } = item;
            let _isCheck: boolean = _buttonIdList.includes( buttonId );
            !_isCheck && _buttonIdList.push( buttonId );
        })

        return _buttonIdList;
    }

    /** 检测空格数 */
    onCheckNullGridNum_blxf () {
        let _nullGridNum: number = 0;

        this.dataList.forEach( item =>{
            let _isNull: boolean = item.onCheckNull_blxf();
            _isNull && _nullGridNum++;
        })

        return _nullGridNum;
    }


    // F1: 1类颜色, Fn: n类颜色
    // Z1: 随机1个颜色，Zn: 随机n个颜色
    // F1_3: 1类颜色数量3个
    // Z2_5: 随机2个颜色数量5个
    // Z0_6: 随机多个颜色总数量6个
    // F1_3/F0_2/F3_2: 从上到下依次为: 1类颜色数量3个、随机类颜色数量2个、3类颜色数量2个

    // Z2_5&2_3: 随机2个颜色数量5个，每个颜色最小为2，最大为3
    // F0_5&0: 随机1个颜色数量5个，且和其它随机颜色不一致
    // Z2_5&1: 随机2个颜色数量5个，至少其中一种颜色和其它随机颜色不一致

    // 1记录已出颜色，2记录不一致颜色
    // 至少其中一种不一致(一种或者都不一致)
    // 已出：【1,2,3,4,5】  至少一种：【6,1,2】

    // 组合结构: 颜色+类型数_数量_附加条件类型_附加条件参数_障碍类型
    // Z2_5&2_3  ==>  Z2_5_1_2&3
    // F0_5&0    ==>  F0_5_2_0
    // Z2_5&1    ==>  Z2_5_2_1

    // F: 颜色种类、Z: 随机颜色种类
    /**
     * 获取发送数据
     * @param str 组合字符串
     * @param maxNum 最大颜色种类
     * @param aroundTopButtons 周围最上层颜色
     * @returns 返回发送数据
     */
    onSendData ( str: string = 'F1_3/F0_2/F3_2', maxNum: number, aroundTopButtons: number[] ) {
        let _sendData: any = { str, numList: [] };

        let _strList: string[] = str.split('/');
        _strList.forEach( ( strItem, index ) =>{
            let _buttons: number[] = index == 0 ? aroundTopButtons : [ _sendData.numList[0] ];
            let {  _numList, _obstacleType } = this.onColorData( strItem, maxNum, _buttons );
            _sendData.numList = _numList.concat( _sendData.numList );
            if ( _obstacleType ) _sendData.obstacleType = _obstacleType;
        })

        UtilsModule_blxf.instance.Log_blxf([ '_sendData >>', _sendData ]);
        return _sendData;
    }

    /**
     * 获取颜色数据
     * @param str 字符串
     * @param maxNum 最大颜色种类
     * @returns 返回颜色数据
     */
    onColorData ( str: string, maxNum: number, filterButtons: number[] ) {
        let _numList: any[] = [], _obstacleType: number;
        let _filterNums: number[] = filterButtons || [];

        // 组合结构: 颜色+类型数_数量_附加条件类型_附加条件参数
        let [ _v1, _v2, _v3, _v4, _v5 ] = str.split('_');
        let [ _t1, _n1 ] = _v1.split('');
        let _isExtra: boolean = _v3 && _v3 != '?';
        let [ _minN, _maxN ] = (_isExtra ? _v4 : '').split('&');
        if ( _isExtra && _v3 != '1' ) _minN = '1';

        // 附加过滤的颜色列表(todo 暂时有问题)
        let _isSpecial: boolean = _v3 == '2';
        if ( _isSpecial ) {
            let _n: number = this.numList1.length - (Number(_n1) - Number(_v4));
            _filterNums = [ ...this.numList1 ].splice(0, _n);
            _filterNums = _filterNums.concat( this.numList2 );
        }

        switch ( _t1 ) {
            case 'F' :
                let _num: number = Number(_n1);
                if ( _num == 0 ) _num = this.onRandomNum( maxNum, _filterNums );

                // 更新已出颜色
                this.onUpdateNumList( _isSpecial ? 2 : 1, _num );

                for ( let _n: number = 0 ; _n < Number(_v2) ; _n++ ) {
                    _numList.push( _num );
                }
                // _numList = new Array( _v2 ).fill( String(_num), 0, Number(_v2) );
                break;
            
            case 'Z' :
                let _nums: number[] = [];
                // 确定种类数
                let _typeN: number = Number(_n1);
                if ( _typeN == 0 ) _typeN = this.onRandomNum( Number(_v2) );
                for( let _n = 0 ; _n < _typeN ; _n ++ ) {
                    let _randomNum: number = this.onRandomNum( maxNum, _filterNums );
                    _nums.push( _randomNum );
                    _filterNums.push( _randomNum );

                    // 更新已出颜色
                    this.onUpdateNumList( _isSpecial ? 2 : 1, _randomNum );
                }

                // 乱序
                _nums.sort((a, b) => Math.random() - 0.5);

                // 加权重值，建立种类池列表
                let _pushN: number = 0;
                let _weightList: any[] = [];
                let _numArrList: number[][] = [];
                _nums.forEach( (item, index) =>{
                    _weightList.push({ item, index, Weight: 5 });

                    // _numArrList[ index ] = [ item ];
                    _numArrList[ index ] = _numArrList[ index ] || [];
                    for ( let i = 0; i < Number(_minN || 1); i++ ) {
                        _numArrList[ index ].push( item );
                        _pushN += 1;
                    }
                })
                
                // 根据权重随机种类，添加到对应种类池
                for ( let _m = 0 ; _m < Number(_v2) - (_pushN || _typeN) ; _m++ ) {
                    // 检测类型最大数量，更新权重值
                    this.onCheckNumArrList( _numArrList, _weightList, Number(_maxN) );

                    let _weightData: any = NumModule_blxf.instance.onWeight_blxf( _weightList );
                    if ( !_weightData ) continue;

                    let { item, index } = _weightData;
                    _numArrList[ index ].push( item );
                }

                // 拼接种类池
                _numArrList.forEach( numArr =>{
                    _numList = _numList.concat( numArr );
                })

                break;
        }

        // 检测障碍物类型
        let [ _type, _typeId ] = ( _v5 || '' ).split('');
        switch ( _type ) {
            case 'P' : _obstacleType = Number( _typeId ); break; 
        }

        return { _numList, _obstacleType };
    }

    /**
     * 更新颜色列表
     * @param type 类型
     * @param num 颜色
     */
    onUpdateNumList ( type: number, num: number ) {
        let _isCheck1: boolean = this.numList1.includes( num );
        let _isCheck2: boolean = this.numList2.includes( num );

        switch ( type ) {
            case 1 : !_isCheck1 && !_isCheck2 && this.numList1.push( num ); break;
            case 2 : !_isCheck1 && !_isCheck2 && this.numList2.push( num ); break;
        }
    }

    /**
     * 检测类型最大数量，更新权重值
     * @param numArrList 类型数量列表
     * @param weightList 权重列表
     * @param maxN 类型最大数量
     */
    onCheckNumArrList ( numArrList: number[][], weightList: any[], maxN: number ) {
        numArrList.forEach( (numArr, index) =>{
            let _isCheck: boolean = numArr.length >= maxN;
            if ( !_isCheck ) return;

            weightList[ index ].Weight = 0;
        })
    }

    /**
     * 随机数
     * @param maxNum 最大值 
     * @param filterNums 过滤值
     * @returns 返回随机数
     */
    onRandomNum ( maxNum: number, filterNums: number[] = [] ) {
        let _randomNum: number = Math.ceil( Math.random() * maxNum );
        
        let _isCheck: boolean = filterNums.includes( _randomNum );

        return _isCheck ? this.onRandomNum( maxNum, filterNums ) : _randomNum;
    }

}
